package reflectdemo;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectClassDemo {

    /**
     * 反射获取对象
     */
    public static void reflectNewInstance() {
        Class<?> c3 = null;
        try {
            // 获取到 class 对象
            c3 = Class.forName("reflectdemo.Student");

            // 获取到 Student 对象
            Student student = (Student) c3.newInstance();

            System.out.println(student);
            student.sleep();

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /**
     * 通过反射 调用构造方法（公开和私有的都可以）
     */
    public static void reflectPrivateConstructor() {
        Class<?> c3 = null;
        try {
            // 获取到 class 对象
            c3 = Class.forName("reflectdemo.Student");

            Constructor<?> constructor = c3.getDeclaredConstructor(String.class, int.class);
            constructor.setAccessible(true); // 构造方法私有，需要设置为 true

            Student student = (Student) constructor.newInstance("frost", 11);

            System.out.println(student);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }

    // 反射私有属性，并修改私有属性
    public static void reflectPrivateFile() {
        Class<?> c3 = null;

        try {
            c3 = Class.forName("reflectdemo.Student");

            Student student = (Student) c3.newInstance();

            Field field = c3.getDeclaredField("age"); // 获取 age 属性
            field.setAccessible(true); // 设置true使类外可以访问私有属性

            field.set(student, 11);

            System.out.println(student);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    // 反射私有方法
    public static void reflectPrivateMethod() {
        Class<?> c3 = null;

        try {
            c3 = Class.forName("reflectdemo.Student");

            Student student = (Student) c3.newInstance();

            Method method = c3.getDeclaredMethod("function", String.class);

            method.setAccessible(true);
            method.invoke(student, "参数!!!");

            System.out.println();


        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //reflectNewInstance();
//        reflectPrivateConstructor();
//        reflectPrivateFile();
//        reflectPrivateMethod();

        func1();
    }

    private static void func1() {
        System.out.println("func1()");
        func2();
    }

    private static void func2() {
        System.out.println("func1()");
        func3();
    }

    private static void func3() {
        System.out.println("func3()");
    }

}
